import {
  getPSUIActionByModelObject,
  IPSAppDataEntity,
  IPSAppDEField,
  IPSAppDERedirectView,
  IPSAppDEUIAction,
  IPSAppDEView,
  IPSAppView,
  IPSAppViewRef,
  IPSNavigateContext,
  IPSNavigateParam,
} from '@ibiz/dynamic-model-api';
import { LogUtil, ModelTool, UIActionTool, Util, ViewTool } from '../../util';
import { IParam, IUIDataParam, IUIEnvironmentParam, IUIUtilParam } from '../../interface';
import { Subject } from 'rxjs';
import { UIActionResult } from '../../logic';
import { AppGlobalUtil } from '../utils';
import { AppDEUIAction } from './app-ui-action';

export class AppFrontAction extends AppDEUIAction {
  /**
   * 初始化AppFrontAction
   *
   * @memberof AppFrontAction
   */
  constructor(opts: IPSAppDEUIAction, context?: any) {
    super(opts, context);
  }

  /**
   * 执行界面行为
   *
   * @param UIDataParam 操作数据参数
   * @param UIEnvironmentParam 操作环境参数
   * @param UIUtilParam 操作工具参数
   * @param srfParentDeName 父值参数
   * @param deUIService 界面UI服务
   * @param context 附加上下文
   * @param params 附加参数
   *
   * @memberof AppFrontAction
   */
  public async execute(
    UIDataParam: IUIDataParam,
    UIEnvironmentParam: IUIEnvironmentParam,
    UIUtilParam: IUIUtilParam,
    deUIService?: any,
    context: any = {},
    params: any = {},
  ) {
    // 处理参数
    const actionParam = this.beforeExecute(UIDataParam, UIEnvironmentParam, UIUtilParam);
    const { actionContext: actionContext, event: event, xData: xData } = actionParam;
    let { args: args } = actionParam;
    // 执行逻辑
    if (Object.is(this.actionModel?.uILogicAttachMode, 'REPLACE')) {
      return this.executeDEUILogic(UIDataParam, UIEnvironmentParam, UIUtilParam);
    }
    const actionTarget: string | null = this.actionModel.actionTarget;
    if (Object.is(actionTarget, 'MULTIDATA')) {
      LogUtil.warn('多项数据暂未支持');
    } else {
      // 处理数据
      let data: any = {};
      let tempData: any = {};
      let parentContext: any = {};
      let parentViewParam: any = {};
      const _this: any = actionContext;
      if (this.actionModel.saveTargetFirst && xData) {
        const result: any = await xData.save(args, false);
        if (Object.is(actionTarget, 'SINGLEDATA')) {
          Object.assign(args[0], result.data);
        } else {
          args = [result.data];
        }
      }
      const _args: any[] = Util.deepCopy(args);
      const appDataEntity = this.actionModel.getPSAppDataEntity();
      if (appDataEntity) {
        const entityName = appDataEntity.codeName.toLowerCase();
        const key = (
          ModelTool.getAppEntityKeyField(appDataEntity) as IPSAppDEField
        )?.codeName.toLowerCase();
        const majorKey = (
          ModelTool.getAppEntityMajorField(appDataEntity) as IPSAppDEField
        )?.codeName.toLowerCase();
        if (_args[0]?.[key]) {
          Object.assign(context, { [entityName!]: `%${key}%` });
        } else {
          Object.assign(context, { [entityName!]: `%${entityName}%` });
        }
        Object.assign(params, { [key!]: `%${key}%` });
        Object.assign(params, { [majorKey]: `%${majorKey}%` });
        if (Object.is(actionTarget, 'SINGLEDATA')) {
          data = args[0];
        }
      }
      // 自定义导航参数优先级大于预置导航参数
      const navgiteContexts: IPSNavigateContext[] | null = this.actionModel.getPSNavigateContexts();
      if (navgiteContexts && navgiteContexts.length > 0) {
        const localContext = Util.formatNavParam(navgiteContexts);
        Object.assign(context, localContext);
      }
      const navgiteParams: IPSNavigateParam[] | null = this.actionModel.getPSNavigateParams();
      if (navgiteParams && navgiteParams.length > 0) {
        const localParam = Util.formatNavParam(navgiteParams);
        Object.assign(params, localParam);
      }
      if (_this.context) {
        parentContext = _this.context;
      }
      if (_this.viewparams) {
        parentViewParam = _this.viewparams;
      }
      context = UIActionTool.handleContextParam(actionTarget, _args, parentContext, parentViewParam, context);
      if (Object.is(actionTarget, 'SINGLEDATA')) {
        tempData = UIActionTool.handleActionParam(actionTarget, _args, parentContext, parentViewParam, params);
        Object.assign(data, tempData);
      } else {
        data = UIActionTool.handleActionParam(actionTarget, _args, parentContext, parentViewParam, params);
      }
      context = Object.assign({}, actionContext.context, context);
      // 构建srfparentdename和srfparentkey
      const parentObj: any = {
        srfparentdename: UIEnvironmentParam.parentDeCodeName ? UIEnvironmentParam.parentDeCodeName : null,
        srfparentkey: UIEnvironmentParam.parentDeCodeName
          ? context[UIEnvironmentParam.parentDeCodeName.toLowerCase()]
          : null,
      };
      Object.assign(data, parentObj);
      Object.assign(context, parentObj);
      const frontPSAppView: IPSAppView | null = this.actionModel.getFrontPSAppView();
      Object.assign(UIDataParam, { navContext: context, navParam: params, data: data });
      return this.oPenView(frontPSAppView, UIDataParam, UIEnvironmentParam, UIUtilParam, deUIService);
    }
  }

  /**
   * 打开视图
   *
   * @param frontPSAppView 打开目标视图
   * @param UIDataParam 操作数据参数
   * @param UIEnvironmentParam 操作环境参数
   * @param UIUtilParam 操作工具参数
   * @param deUIService 界面UI服务
   *
   * @return {*}
   * @memberof AppFrontAction
   */
  async oPenView(
    frontPSAppView: any,
    UIDataParam: IUIDataParam,
    UIEnvironmentParam: IUIEnvironmentParam,
    UIUtilParam: IUIUtilParam,
    deUIService?: any,
  ): Promise<any> {
    const { data: args, sender: actionContext, navContext: context, navParam: viewparam } = UIDataParam;
    const { ctrl: xData } = UIEnvironmentParam;
    // 打开HTML
    return new Promise(async (resolve: any, reject: any) => {
      //打开视图后续逻辑
      const openViewNextLogic: any = async (actionModel: any, resultData?: any) => {
        if (actionModel.reloadData && xData && xData.refresh && xData.refresh instanceof Function) {
          if (args && args.length > 0) {
            Object.assign(args[0], { 'refreshMode': actionModel.refreshMode });
            xData.refresh(args);
          } else {
            xData.refresh([{ 'refreshMode': actionModel.refreshMode }]);
          }
        }
        if (actionModel.closeEditView) {
          actionContext.closeView(null);
        }
        Object.assign(UIDataParam, { data: resultData });
        // 后续界面行为
        if (this.actionModel.M?.getNextPSUIAction) {
          const nextUIaction: any = await getPSUIActionByModelObject(this.actionModel);
          if (nextUIaction.getPSAppDataEntity()) {
            const [tag, appDeName] = (nextUIaction as IPSAppDEUIAction).id.split('@');
            if (deUIService) {
              return deUIService.excuteAction(tag, UIDataParam, UIEnvironmentParam, UIUtilParam, appDeName);
            }
          } else {
            return AppGlobalUtil.executeGlobalAction(nextUIaction.id, UIDataParam, UIEnvironmentParam, UIUtilParam);
          }
        } else {
          if (Object.is(actionModel?.uILogicAttachMode, 'AFTER')) {
            if (actionContext.context) {
              Object.assign(context, actionContext.context);
            }
            return this.executeDEUILogic(UIDataParam, UIEnvironmentParam, UIUtilParam);
          } else {
            return new UIActionResult({ ok: true, result: resultData });
          }
        }
      };
      if (Object.is(this.actionModel.frontProcessType, 'OPENHTMLPAGE') && this.actionModel.htmlPageUrl) {
        const url = Util.fillStrData(this.actionModel.htmlPageUrl, context, viewparam);
        window.open(url, '_blank');
        resolve(new UIActionResult({ ok: true, result: viewparam }));
        // 打开顶级视图，打开顶级视图或向导（模态）
      } else if (
        Object.is(this.actionModel.frontProcessType, 'TOP') ||
        Object.is(this.actionModel.frontProcessType, 'WIZARD')
      ) {
        if (!this.actionModel.getFrontPSAppView()) {
          LogUtil.warn('未找到打开目标视图');
          return;
        }
        await frontPSAppView?.fill(true);
        if (!frontPSAppView) {
          return;
        }
        // 准备deResParameters参数和parameters参数
        let deResParameters: any[] = [];
        let parameters: any[] = [];
        if (frontPSAppView.getPSAppDataEntity()) {
          // 处理视图关系参数 （只是路由打开模式才计算）
          if (
            !frontPSAppView.openMode ||
            frontPSAppView.openMode == 'INDEXVIEWTAB' ||
            frontPSAppView.openMode == 'POPUPAPP'
          ) {
            deResParameters = Util.formatAppDERSPath(context, (frontPSAppView as IPSAppDEView).getPSAppDERSPaths());
          }
        }
        if (!frontPSAppView.openMode || frontPSAppView.openMode == 'INDEXVIEWTAB') {
          if (frontPSAppView.getPSAppDataEntity()) {
            parameters = [
              {
                pathName: Util.srfpluralize(
                  (frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName,
                ).toLowerCase(),
                parameterName: (frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName.toLowerCase(),
              },
              {
                pathName: 'views',
                parameterName: ((frontPSAppView as IPSAppDEView).getPSDEViewCodeName() as string).toLowerCase(),
              },
            ];
          } else {
            parameters = [{ pathName: 'views', parameterName: frontPSAppView.codeName.toLowerCase() }];
          }
        } else {
          if (frontPSAppView.getPSAppDataEntity()) {
            parameters = [
              {
                pathName: Util.srfpluralize(
                  (frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName,
                ).toLowerCase(),
                parameterName: (frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName.toLowerCase(),
              },
            ];
          }
          if (frontPSAppView && frontPSAppView.modelPath) {
            Object.assign(context, { viewpath: frontPSAppView.modelPath });
          }
        }
        // 打开重定向视图
        if (frontPSAppView.redirectView) {
          const data = (args as IParam[])[0];
          const field: IPSAppDEField | null = (frontPSAppView as IPSAppDERedirectView).getTypePSAppDEField();
          if (field) {
            const type = data[field.codeName.toLocaleLowerCase()];
            const appViewRefs = (frontPSAppView as IPSAppDERedirectView).getRedirectPSAppViewRefs()!;
            let appViewRef: IPSAppViewRef | undefined = appViewRefs?.find(
              (appViewRef: IPSAppViewRef) => appViewRef.name === type || appViewRef.name === `EDITVIEW:${type}`,
            );
            if (!appViewRef) {
              appViewRef = appViewRefs?.find((appViewRef: IPSAppViewRef) => {
                const entityName = frontPSAppView.getPSAppDataEntity()?.name;
                return appViewRef.name === type || appViewRef.name === `${entityName}:EDITVIEW:${type}`;
              });
            }
            if (appViewRef) {
              const appView: any = await appViewRef.getRefPSAppView()?.fill();
              return this.oPenView(appView, UIDataParam, UIEnvironmentParam, UIUtilParam, deUIService);
            }
          }
        } else if (!frontPSAppView.openMode || frontPSAppView.openMode == 'INDEXVIEWTAB') {
          const routePath = ViewTool.buildUpRoutePath(context, deResParameters, parameters, [], (args as IParam[])[0]);
          App.getOpenViewService().openView(routePath);
          resolve(openViewNextLogic(this.actionModel, args));
        } else if (frontPSAppView.openMode == 'POPUPMODAL') {
          const container: Subject<any> = App.getOpenViewService().openModal(
            { viewModel: frontPSAppView },
            context,
            viewparam,
            UIDataParam.navData,
          );
          container.subscribe((result: any) => {
            if (!result || !Object.is(result.ret, 'OK')) {
              return;
            }
            resolve(openViewNextLogic(this.actionModel, result.datas));
          });
        } else if (frontPSAppView.openMode?.indexOf('DRAWER') !== -1) {
          const container: Subject<any> = App.getOpenViewService().openDrawer(
            { viewModel: frontPSAppView },
            context,
            viewparam,
            UIDataParam.navData,
          );
          container.subscribe((result: any) => {
            if (!result || !Object.is(result.ret, 'OK')) {
              return;
            }
            resolve(openViewNextLogic(this.actionModel, result.datas));
          });
        } else if (frontPSAppView.openMode === 'POPUP') {
          LogUtil.warn(`${frontPSAppView.openMode}打开视图方式暂未实现`);
        } else if (frontPSAppView.openMode == 'POPOVER') {
          LogUtil.warn(`${frontPSAppView.openMode}打开视图方式暂未实现`);
        } else {
          LogUtil.warn(`${frontPSAppView.openMode}打开视图方式暂未实现`);
        }
        // 用户自定义
      } else {
        LogUtil.warn(`${this.actionModel.caption}自定义界面行为空执行`);
      }
    });
  }
}
